﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LowLevelGraphics;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Used for motion detection
    /// </summary>
    public class MotionDetection2 : BaseImageFilter, ITwoSourceFilter
    {
        protected int m_nThreshold = 100;
        protected Color m_DetectionColor = Color.Black;

        public MotionDetection2()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MotionDetection2"/> class.
        /// </summary>
        /// <param name="_nThreshold">The _n threshold.</param>
        /// <param name="_detectionColor">Color of the _detection.</param>
        public MotionDetection2(int _nThreshold, Color _detectionColor)
        {
            m_nThreshold = _nThreshold;
            m_DetectionColor = _detectionColor;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MotionDetection2"/> class.
        /// </summary>
        /// <param name="_motionDetection2">The _motion detection2.</param>
        internal MotionDetection2(MotionDetection2 _motionDetection2)
        {
        }

        #region ITwoSourceFilter Members

        /// <summary>
        /// Runs the motion detection algorithm
        /// </summary>
        /// <param name="_newImage">The _new image.</param>
        /// <param name="_oldImage">The _old image.</param>
        /// <returns>
        /// A bitmap indicating where changes between frames have occurred overlayed on top of the new image.
        /// </returns>
        public UnsafeBitmap Process(UnsafeBitmap _newImage, UnsafeBitmap _oldImage)
        {
            UnsafeBitmap NewImage1 = new Threshold2().Execute(_newImage);
            UnsafeBitmap OldImage1 = new Threshold2().Execute(_oldImage);
            UnsafeBitmap NewImage2 = new GaussianBlur(5).Execute(NewImage1);
            NewImage1.Dispose();
            UnsafeBitmap OldImage2 = new GaussianBlur(5).Execute(OldImage1);
            OldImage1.Dispose();

            UnsafeBitmap OutputImage = (UnsafeBitmap)_newImage.Clone();
            UnsafeBitmap Overlay = (UnsafeBitmap)_newImage.Clone();

            for (int x = 0; x < OutputImage.Width; ++x)
            {
                for (int y = 0; y < OutputImage.Height; ++y)
                {
                    Color NewPixel = NewImage2.GetPixel(x, y);
                    Color OldPixel = OldImage2.GetPixel(x, y);
                    OutputImage.SetPixel(x, y, NewPixel);
                    if (Math.Pow((double)(NewPixel.R - OldPixel.R), 2.0) > m_nThreshold)
                    {
                        Overlay.SetPixel(x, y, Color.FromArgb(100, 0, 100));
                    }
                    else
                    {
                        Overlay.SetPixel(x, y, Color.FromArgb(200, 0, 200));
                    }
                }
            }
            OldImage2.Dispose();
            NewImage2.Dispose();
            UnsafeBitmap Overlay2 = new ColorEdgeDetection(25, m_DetectionColor).Execute(Overlay);
            for (int x = 0; x < OutputImage.Width; ++x)
            {
                for (int y = 0; y < OutputImage.Height; ++y)
                {
                    Color Pixel1 = Overlay2.GetPixel(x, y);
                    if (Pixel1.R != m_DetectionColor.R || Pixel1.G != m_DetectionColor.G || Pixel1.B != m_DetectionColor.B)
                    {
                        Overlay2.SetPixel(x, y, Color.FromArgb(200, 0, 200));
                    }
                }
            }
            Overlay.Dispose();
            UnsafeBitmap ReturnImage = BitmapFunctions.Watermark(OutputImage, Overlay2, 1.0f, 0, 0, Color.FromArgb(200, 0, 200));
            Overlay2.Dispose();
            OutputImage.Dispose();
            return ReturnImage;
        }

        #endregion

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new MotionDetection2(this);
        }
    }
}
